using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using SideShow.Contents;
using System.IO;

namespace SideShow
{
    [Serializable]
    public class SideShowEndpoint : SideShowObject
    {
        public const string ScfFormat = "A9A5353F-2D4B-47ce-93EE-759F3A7DDA4F";
        public const string ICalFormat = "4DFF36B5-9DDE-4F76-9A2A-96435047063D";
        public static readonly Guid ScfFormatId = new Guid(ScfFormat);
        public static readonly Guid ICalFormatId = new Guid(ICalFormat);

        private Guid _id;
        private Dictionary<uint, Content> _content;


        [NonSerialized]
        private EventHandler<ContentEventArgs> _contentAdded;
        [NonSerialized]
        private EventHandler<ContentEventArgs> _contentRemoved;
        [NonSerialized]
        private EventHandler _allContentRemoved;

        public event EventHandler<ContentEventArgs> ContentAdded
        {
            add { _contentAdded += value; }
            remove { _contentAdded -= value; }
        }

        public event EventHandler<ContentEventArgs> ContentRemoved
        {
            add { _contentRemoved += value; }
            remove { _contentRemoved -= value; }
        }

        public event EventHandler AllContentRemoved
        {
            add { _allContentRemoved += value; }
            remove { _allContentRemoved -= value; }
        }
        
        internal SideShowEndpoint(BinaryReader reader)
        {
            DeserializeObject(reader);
        }

        public SideShowEndpoint(Guid id)
        {
            _id = id; // GetEndpointId(this.GetType());
            _content = new Dictionary<uint, Content>();
        }

        public Guid Id
        {
            get { return _id; }
        }

        public Content GetContent(uint contentId)
        {
            Content content = null;
            _content.TryGetValue(contentId, out content);
            return content;
        }

        public bool ContentExists(Content content)
        {
            return _content.ContainsValue(content);
        }

        public void AddContent(Content newContent)
        {
            if (_content.ContainsKey(newContent.Id))
            {
                _content[newContent.Id] = newContent;
            }
            else
            {
                _content.Add(newContent.Id, newContent);
            }
            OnContentAdded(newContent);
        }

        public void RemoveContent(uint contentId)
        {
            if (_content.ContainsKey(contentId))
            {
                Content content = _content[contentId];
                _content.Remove(contentId);
                OnContentRemoved(content);
            }
            
        }

        public void RemoveAllContent()
        {
            _content.Clear();
            OnAllContentRemoved();
        }

        protected virtual void OnContentAdded(Content content)
        {
            if (_contentAdded != null)
            {
                _contentAdded(this, new ContentEventArgs(content));
            }
        }

        protected virtual void OnContentRemoved(Content content)
        {
            if (_contentRemoved != null)
            {
                _contentRemoved(this, new ContentEventArgs(content));
            }
        }

        protected virtual void OnAllContentRemoved()
        {
            if (_allContentRemoved != null)
            {
                _allContentRemoved(this, EventArgs.Empty);
            }
        }

        protected internal override void DeserializeObject(System.IO.BinaryReader reader)
        {
            base.DeserializeObject(reader);
            byte[] buf = reader.ReadBytes(16);
            _id = new Guid(buf);
            int l = reader.ReadInt32();
            _content = new Dictionary<uint, Content>();
            for (int i = 0; i < l; i++)
            {
                string typeName = reader.ReadString();
                Type t = Type.GetType(typeName);
                Content c = (Content)Activator.CreateInstance(t);
                c.DeserializeObject(reader);
                _content.Add(c.Id, c);
            }
        }

        protected internal override void SerializeObject(System.IO.BinaryWriter writer)
        {
            base.SerializeObject(writer);
            writer.Write(_id.ToByteArray());
            writer.Write(_content.Count);
            foreach (KeyValuePair<uint, Content> entry in _content)
            {
                writer.Write(entry.Value.GetType().FullName);
                entry.Value.SerializeObject(writer);
            }
        }
    }
}
